home *** CD-ROM | disk | FTP | other *** search
- LAST UPDATE: July 15, 1992
-
- All examples have been built successfully with Motif 1.1.3, 1.1.4, and 1.2,
- as well as C++ 2.1 and C++ 3.0 on a Silicon Graphics IRIS Indigo. Note that
- a few minor changes from the sources described in the book were required to
- compile under C++ 3.0 and Motif 1.2. More details below.
-
- The sources are mostly organized by chapters, with each example being
- placed in a directory that corresponds to the chapter in which it is
- discussed. The exception is those C++ classes that are considerred part of
- a library. There are two libraries. The first is libComponent.a, used by
- the first part of the book. This is a very small library, and those classes
- are found in the ComponentLib directory. The second, somewhat larger
- library is libMotifApp.a, which is developed in the second part of the
- book. This library lives in the MotifApp directory.
-
- If you have lots of disk space, just type "make" in this top-level
- directory to build all examples. You can also type "make clobber" to remove
- all binaries from subdirectories. If you have less disk space, just build
- the libraries and build only those examples you are interested in.
-
- The Makefiles have been kept very simple to allow you to modify them to
- meet your needs. They make no pretense at being robust or portable. They
- are not tested
-
- In addition to the sources to the examples in the book, you will find an
- "Extras" subdirectory. This directory contains a few alternate
- implementations of some examples in the book, and also contains some
- written material that was cut from the final version of the book, but which
- may be useful to some people.
-
- CHANGES FOR C++ 3.0
-
- The TicTacToe uses enumerated types encapsulated within a class.
- Unfortunately, the way C++ treats such types changed between 2.0 and 3.0,
- and it appears to be impossible to come up with an approach that satifies
- both and keeps the type encpasulated. These types have been moved outside
- the class to accomodate both versions of C++, at the loss of encapsulation.
-
- CHANGES FOR MOTIF 1.2 AND R5
-
- To build these examples with X11 R5 and Motif 1.2, you must change all
- declarations of argc as an unsigned int to be just an int. These have been
- ifdef'd with
-
- #if (XlibSpecificationRelease>=5)
-
- in the examples.
-
- The call to XrmMergeDatabases() in UIComponent seems to cause problems in
- R5, as well. Using the new R5 function, XrmCombineDatabase, when building
- with R5 seems to solve the problem.
-
- Note that for R5, no compilation flags are necessary to activate function
- prototypes in Xt.
-
- BUILD PROBLEMS WITH Motif 1.1
-
- Some vendor's distributions of Motif appear to still have C++ keywords in
- public header files. If you encounter compile errors due to the words "new"
- or "class" in a Motif header, simply change the offending variable names to
- something else. These problems appear to be completely gone in Motif 1.2.
-
- Also: Some versions of Xt (R4) expect XTFUNCPROTO to be defined instead of
- FUNCPROTO, as discussed in the book. The makefiles have been modified to
- use both.
-
- PORTABILITY PROBLEMS
-
- Someone pointed out that I use the function strdup() periodically, which is
- a non-standard function. If you don't have this function, it is simple to
- write an equivalent, of course:
-
- char * my_strdup(const char *str)
- {
- // not robust, but neither is strdup
-
- char *newStr = new char[strlen(str) + 1];
- strcpy(newStr, str);
- return (newStr);
- }
-
- srand48/drand48 is apparently not available on all systems. A contributed
- (untested) fix is to put these lines in the MoveGenerator class file:
-
- #include "stdlib.h"
- void srand48(long seed){srand((int)seed);}
- #define RAND_MAX 2147483647 // should not be needed
- double drand48(void){ return ((double)rand())/(double)RAND_MAX; }
-
-
- I have had several other reports of trouble compiling with g++. However,
- many people report success at building with an assortment of other
- compilers. Known problems with g++:
-
- In ButtonInterface.C, the call to XtAddCallback references a protected
- static member of the CmdInterface base class as
- CmdInterface::executeCmdCallback. g++ doesn't like this, but will accept
- just executeCmdCallback.
-
- In some cases g++ doesn't appear to properly initialize non-local static
- objects, MotifApp's UndoCmd, for example. A contributed solution is to
- include UndoCmd.h in the same file as main, which g++ then handles correctly
- for some reason.
-
- IMPORTANT NOTE: There is an assumption in the approach described and
- demonstrated in the book that calling conventions between C and C++ are the
- same. Specifically, it is expected that the argument order of static member
- functions is the same as that of C functions, so that static member
- functions can be registered as callbacks and called from C. This is
- generally true of most current C++ compilers, but the C++ spec allows for
- implementations that do not meet this criteria. Reportedly, there is at
- least one native compiler implementation whose calling conventions passes
- C++ arguments in the reverse order of that used by C! For such a compiler,
- these sources will obviously not work. The concepts in the book are still
- valid, but as an implementation issue, if you have such a compiler, you
- must use friend functions rather than static member functions, as initially
- described in the book, and you must declared these functions as extern "C".
-
-
- ERRORS FOUND IN FIRST PRINTING
-
- Page 62:
- --------
-
- Line 10 in the code example is not needed. There is no regular
- checkPassWord() function. This is a left-over from the previous example.
- To be fixed in a future printing.
-
- Page 229
- -------
-
- SetValues should use MODAL, not MODEL
-
- Page 374
- --------
-
- Callbacks are installed incorrectly, Both a cancel and an ok callback
- should be installed. In the text, the cancel is installed as the
- okCallback.
-
- HSView class, page 367
- ----------------------
-
- The protected member function should be declared as:
-
- void RGBToHSV ( int, int, int, int&, int&, int& );
-
- not as:
-
- void HSVView::RGBToHSV ( int, int, int, int&, int&, int& );
-
- No harm done, at least with my compiler, but the class qualification is
- unecessary.
-
- WordCountWindow class, chapter 10, page 326
- --------------------------------------------
-
- The member function createMenuPanes() should be declared as:
-
- virtual void createMenuPanes();
-
- not
-
- virtual void WordCountWindow::createMenuPanes();
-
-
- NAME CHANGES:
-
- In the stopwatch and tictactoe examples, found in directories ch3A, ch3B,
- and ch5, the names of the driver or body of the programs, as used in the
- book, had the same name as a class in the same directory, but with a
- different case. For example, main() is defined in tictactoe.C, in the book.
- This causes installation problems when loaded on systems that are not case
- sensitive (PCs and Macs). Therefore, the problem files in these directories
- have been renamed "main.C".
-
- VARIOUS CLASSES IN MOTIFAPP DIRECTORY:
-
- All examples were tested using a 2.0 cfront that had a number of 2.1
- features implemented. Among them - 2.1 allows classes to inherit pure
- virtual member functions, pure 2.0 does not. Several classes, as described
- in the book expect to inherit pure virtuals. I have added the the pure
- virtual declaration in the derived classes to the sources for those using
- 2.0 C++. These are ifdef'd with "#ifndef CPLUSPLUS2_1" to indicate the
- changes. The added declaration will work with both 2.0 and 2.1. The ifdef
- is purely to indicate something that is different from the text of the
- book.
-
-
- PROBLEMS IN TEXT, SECOND PARAGRAPH, page 87
-
- This paragraph is misleading. A future printing will read:
-
- The Intrinsics destruction sequence for widgets can be particularly
- troublesome, although necessary. For example, consider the stopwatch
- example described earlier in this chapter. If the application were to
- destroy the program's top-level shell widget before deleting the Stopwatch
- object, the integrity of every object in the Stopwatch subsystem would be
- compromised. When a widget is destroyed, Xt automatically destroys all the
- widget's children. So, destroying a widget that serves as the parent of a
- Stopwatch object ultimately destroys the widgets created by the Stopwatch
- object, and also the widgets created by the Face and Control objects.
- Therefore, destroying a widget can potentially free data members that are
- supposedly accessible only from within an object. This represents a fairly
- serious breach in the encapsulation of the component. Although this
- scenario may seem contrived, such situations can easily occur in more
- complex programs
-
-
- PAGES 108-109
-
- A last minute reorganization produced some backward references to things
- that had not yet been introduced:
-
- 1ST FULL PARAGRAPH, page 108, should read:
-
- Derived classes may be either specializations or generalizations of the
- original base class. Specializations start from a general-purpose base
- class and move toward a specific purpose. For example, Chapter 2 starts
- with a general Password class and then derives a StrictPassword class that
- adds additional features and alters the behavior of the base class.
- Sometimes the derived class adds additional features and is intended to be
- used in a wider range of situations than the base class. For example, the
- UIComponent class extends the protocol defined by the BasicComponent class
- to provide a more generally useful class.
-
- 1st FULL PARAGRAPH, page 109, should read:
-
- Sometimes it is clear that a task needs to be performed, but it is less
- clear which object should do it. It is useful to consider all the
- activities in a system and be sure some object is responsible for each
- action. Sometimes, the responsibility for a particular task can be assigned
- to an object that has already been identified. At other times, the action
- may suggest that a new type of object should be added to the system. For
- example, in the Password class discussed in Chapter 2, it is apparent that
- there is a need to maintain a list of valid passwords somewhere. We might
- decide that this responsibility does not really belong in the user
- interface component that accepts the password from the user. Instead, we
- could create a second class, a PasswordDatabase class, to perform that
- function.
-
-
-
-
-